package com.example.cyk.service.impl;

import com.example.cyk.common.JwtUtils;
import com.example.cyk.config.exception.ApplicationException;
import com.example.cyk.config.response.AppReturn;
import com.example.cyk.config.response.CodeMsg;
import com.example.cyk.mapper.UserMapper;
import com.example.cyk.mapper.UserinfoMapper;
import com.example.cyk.model.User;
import com.example.cyk.model.Userinfo;
import com.example.cyk.model.vo.UserVO;
import com.example.cyk.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;


@Slf4j
@Service
public class UserServiceImpl implements IUserService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserinfoMapper userinfoMapper;

    @Override
    public UserVO login(String username, String password) {
        //1.非空校验
        if(!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
            log.warn(CodeMsg.FAIL_NULL_USERNAME_OR_PASSWORD.toString());
            throw new ApplicationException(AppReturn.fail(CodeMsg.FAIL_NULL_USERNAME_OR_PASSWORD));
        }
        //2.校验用户名和密码
        User dbUser = userMapper.selectUserByName(username);
        if(dbUser == null || !dbUser.getPassword().equals(password)) {
            log.warn(CodeMsg.FAIL_ERROR_USERNAME_OR_PASSWORD.toString());
            throw new ApplicationException(AppReturn.fail(CodeMsg.FAIL_ERROR_USERNAME_OR_PASSWORD));
        }
        //3.jwt + redis 保存用户身份
        //jwt 是为了解决使用 session 大量占用服务器内存的问题
        //redis 上也要保存一份，是有些用户 "修改密码" 或者防止 "恶意破坏" 直接对用户进行下线操作
        //1) 生成 Token.
        Map<String, String> map = new HashMap<>();
        map.put("username", username);
        String token = JwtUtils.createToken(map);
        //2) 存入 redis
        redisTemplate.opsForValue().set(username, token);
        //4.返回用户数据
        UserVO userVO = new UserVO();
        dbUser.setPassword("");
        BeanUtils.copyProperties(dbUser, userVO);
        userVO.setToken(token);
        return userVO;
    }

    @Override
    public void logout(String username) {
        //1.非空检验
        if(!StringUtils.hasLength(username)) {
            log.warn(CodeMsg.FAIL_NULL_USERNAME.toString());
            throw new ApplicationException(AppReturn.fail(CodeMsg.FAIL_NULL_USERNAME));
        }
        //2.删除 Token 数据
        redisTemplate.delete(username);
    }

    @Override
    public void reg(UserVO user) {
        //1.非空校验
        if(user == null || !StringUtils.hasLength(user.getUsername()) ||
                !StringUtils.hasLength(user.getPassword()) ||
                !StringUtils.hasLength(user.getNickname())) {
            log.warn(CodeMsg.FAIL_NULL_NAME_OR_NICK_OR_PASSWORD.toString());
            throw new ApplicationException(AppReturn.fail(CodeMsg
                    .FAIL_NULL_NAME_OR_NICK_OR_PASSWORD));
        }
        //2.检验用户名是否存在
        User dbuser = userMapper.selectUserByName(user.getUsername());
        if(dbuser != null) {
            log.warn(CodeMsg.FAIL_EXISTS_USERNAME.toString());
            throw new ApplicationException(AppReturn.fail(CodeMsg.FAIL_EXISTS_USERNAME));
        }
        //3.注册用户信息
        regUser(user);
    }

    @Override
    public Userinfo getUserinfo(Long userId) {
        //1.非空校验
        if(userId == null) {
            log.warn(CodeMsg.FAIL_NULL_USERID.toString());
            throw new ApplicationException(AppReturn.fail(CodeMsg.FAIL_NULL_USERID));
        }
        //2.获取用户数据
        Userinfo userinfo = userinfoMapper.selectUserinfoById(userId);
        if(userinfo == null) {
            log.warn(CodeMsg.FAIL_NOT_EXISTS_USERINFO.toString());
            throw new ApplicationException(AppReturn.fail(CodeMsg.FAIL_NOT_EXISTS_USERINFO));
        }
        return userinfo;
    }

    /**
     * reg 中的注册用户信息
     * @param userVO
     */
    private void regUser(UserVO userVO) {
        //1.注册用户身份
        User user = new User();
        user.setUsername(userVO.getUsername());
        user.setPassword(userVO.getPassword());
        userMapper.add(user);
        //2.注册用户基本信息
        Long userId = userMapper.selectUserByName(user.getUsername()).getId();
        Userinfo userinfo = new Userinfo();
        userinfo.setUserId(userId);
        userinfo.setNickname(userVO.getNickname());
        userinfoMapper.add(userinfo);
    }

}
